/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.appyvet.rangebarsample.slice;

import com.appyvet.materialrangebar.RangeBar;
import com.appyvet.rangebarsample.ComponentColor;
import com.appyvet.rangebarsample.ResourceTable;
import com.appyvet.rangebarsample.colorpicker.ColorPickerDialog;
import com.appyvet.rangebarsample.utils.LogUtil;
import com.appyvet.rangebarsample.utils.ResUtil;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;

import ohos.agp.components.element.ShapeElement;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Text;
import ohos.agp.components.Component;
import ohos.agp.components.Slider;
import ohos.agp.components.Checkbox;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.AbsButton;
import ohos.agp.utils.Color;
import ohos.app.Context;

import java.util.Locale;

/**
 * This class is initialize all UI
 * components and call library apis
 * to show it's usage.
 */
public class MainAbilitySlice extends AbilitySlice implements
        ColorPickerDialog.OnColorSelectedListener {
    private static final String TAG = ColorPickerDialog.class.getSimpleName();

    // Sets variables to save the colors of each attribute
    private int mBarColor;

    private int mConnectingLineColor;

    private int mPinColor;
    private int mTextColor;

    private int mTickColor;

    // Initializes the RangeBar in the application
    private RangeBar rangebar;

    private int mThumbColor;

    private int mThumbBoundaryColor;

    private int mTickLabelColor;

    private int mTickLabelSelectedColor;

    // color chooser dialog
    private int selectedColor;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        initComponents();
    }

    /**
     * Set background of the background and returns it.
     *
     * @param shape the particular shape i.e. RECTANGLE, CIRCLE etc
     * @param backgroundColor the background color of component
     * @param strokeColor the boundary color of component
     * @param radius the radius of boundary of component
     *
     * @return ShapeElement returns the final ShapeElement of component
     */
    public final ShapeElement getBackground(int shape, int backgroundColor,
                                        int strokeColor, float radius) {
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setShape(shape);
        shapeElement.setRgbColor(RgbColor.fromArgbInt(ResUtil.getColor(this, backgroundColor)));
        shapeElement.setCornerRadius(radius);
        shapeElement.setStroke(5, RgbColor.fromArgbInt(ResUtil.getColor(this, strokeColor)));
        return shapeElement;
    }

    private void initComponents() {
        final Text barColor = (Text) findComponentById(ResourceTable.Id_barColor);
        final Text thumbBoundaryColor = (Text) findComponentById(ResourceTable.Id_thumbBoundaryColor);
        final Text connectingLineColor = (Text) findComponentById(ResourceTable.Id_connectingLineColor);
        final Text pinColor = (Text) findComponentById(ResourceTable.Id_pinColor);
        final Text pinTextColor = (Text) findComponentById(ResourceTable.Id_textColor);
        final Text tickColor = (Text) findComponentById(ResourceTable.Id_tickColor);
        final Text thumbColor = (Text) findComponentById(ResourceTable.Id_thumbColor);
        final Text rangeButton = (Text) findComponentById(ResourceTable.Id_enableRange);
        final Text disabledButton = (Text) findComponentById(ResourceTable.Id_disable);
        final Text tickBottomLabelsButton = (Text) findComponentById(ResourceTable.Id_toggleTickBottomLabels);
        final Text tickTopLabelsButton = (Text) findComponentById(ResourceTable.Id_toggleTickTopLabels);
        final Text tickLabelColor = (Text) findComponentById(ResourceTable.Id_tickLabelColor);
        final Text tickLabelSelectedColor = (Text) findComponentById(ResourceTable.Id_tickLabelSelectColor);
        final Text thumbListContainerView = (Text) findComponentById(ResourceTable.Id_thumbListContainerView);
        final Text tvLeftIndex = (Text) findComponentById(ResourceTable.Id_tvLeftIndex);
        final Text tvRightIndex = (Text) findComponentById(ResourceTable.Id_tvRightIndex);
        final Text tvLeftValue = (Text) findComponentById(ResourceTable.Id_tvLeftValue);
        final Text tvRightValue = (Text) findComponentById(ResourceTable.Id_tvRightValue);

        selectedColor = ResUtil.getColor(this, ResourceTable.Color_primary);

        tickColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        thumbColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        rangeButton.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        disabledButton.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        tickBottomLabelsButton.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        tickTopLabelsButton.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        tickLabelColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        pinTextColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        pinColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        connectingLineColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        thumbBoundaryColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        barColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        tickLabelSelectedColor.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        thumbListContainerView.setBackground(getBackground(ShapeElement.RECTANGLE,
                ResourceTable.Color_white, ResourceTable.Color_material_lighter_gray, 5.0f));

        // Gets the RangeBar
        rangebar = (RangeBar) findComponentById(ResourceTable.Id_rangebar1);

        rangeButton.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                rangebar.setRangeBarEnabled(!rangebar.isRangeBar());
            }
        });
        disabledButton.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                rangebar.setEnabled(!rangebar.isEnabled());
            }
        });

        // Sets the display values of the indices
        rangebar.setOnRangeBarChangeListener(new RangeBar.OnRangeBarChangeListener() {
            @Override
            public void onRangeChangeListener(RangeBar rangeBar, int leftPinIndex,
                                                int rightPinIndex, String leftPinValue, String rightPinValue) {
                tvLeftIndex.setText(String.format(Locale.ROOT, "Left Index %d", leftPinIndex));
                tvRightIndex.setText(String.format(Locale.ROOT, "Right Index %d", rightPinIndex));

                tvLeftValue.setText(String.format("Left Value %s", leftPinValue));
                tvRightValue.setText(String.format("Right Value %s", rightPinValue));
            }

            @Override
            public void onTouchEnded(RangeBar rangeBar) {
                LogUtil.debug(TAG, "Touch ended");
            }

            @Override
            public void onTouchStarted(RangeBar rangeBar) {
                LogUtil.debug(TAG, "Touch started");
            }
        });

        // Setting Number Attributes -------------------------------

        // Sets tickStart
        final Text tickStart = (Text) findComponentById(ResourceTable.Id_tickStart);
        Slider tickStartSeek = (Slider) findComponentById(ResourceTable.Id_tickStartSeek);
        tickStartSeek.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
                try {
                    rangebar.setTickStart(progress);
                } catch (IllegalArgumentException e) {
                    LogUtil.error(TAG, e.getMessage());
                }
                tickStart.setText("tickStart = " + progress);
            }

            @Override
            public void onTouchStart(Slider slider) { }

            @Override
            public void onTouchEnd(Slider slider) { }
        });

        // Sets tickEnd
        final Text tickEnd = (Text) findComponentById(ResourceTable.Id_tickEnd);
        Slider tickEndSeek = (Slider) findComponentById(ResourceTable.Id_tickEndSeek);
        tickEndSeek.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
                try {
                    rangebar.setTickEnd(progress);
                } catch (IllegalArgumentException e) {
                    LogUtil.error(TAG, e.getMessage());
                }
                tickEnd.setText("tickEnd = " + progress);
            }

            @Override
            public void onTouchStart(Slider slider) { }

            @Override
            public void onTouchEnd(Slider slider) { }
        });

        // Sets tickInterval
        final Text tickInterval = (Text) findComponentById(ResourceTable.Id_tickInterval);
        Slider tickIntervalSeek = (Slider) findComponentById(ResourceTable.Id_tickIntervalSeek);
        tickIntervalSeek.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
                try {
                    rangebar.setTickInterval(progress);
                } catch (IllegalArgumentException e) {
                    LogUtil.error(TAG, e.getMessage());
                }
                tickInterval.setText("tickInterval = " + progress);
            }

            @Override
            public void onTouchStart(Slider slider) { }

            @Override
            public void onTouchEnd(Slider slider) { }
        });

        // Sets Minimum Thumb Distance
        final Text minThumbDistance = (Text) findComponentById(ResourceTable.Id_minThumbDistance);
        Slider minThumbDistanceSeek = (Slider) findComponentById(ResourceTable.Id_minThumbDistanceSeek);
        minThumbDistanceSeek.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
                // We want minimum value to be -1 instead of 0 (For ignoring the thumb distance)
                // So that is why we subtract -1
                int newProgress = progress - 1;
                try {
                    rangebar.setMinimumThumbDistance(newProgress);
                } catch (IllegalArgumentException e) {
                    LogUtil.error(TAG, e.getMessage());
                }
                minThumbDistance.setText("Min Thumb Distance = " + newProgress);
            }

            @Override
            public void onTouchStart(Slider slider) { }

            @Override
            public void onTouchEnd(Slider slider) { }
        });

        // Sets barWeight
        final Text barWeight = (Text) findComponentById(ResourceTable.Id_barWeight);
        Slider barWeightSeek = (Slider) findComponentById(ResourceTable.Id_barWeightSeek);
        barWeightSeek.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
                rangebar.setBarWeight(convertDpToPixel(progress, MainAbilitySlice.this));
                barWeight.setText(String.format(Locale.ROOT, "barWeight = %ddp", progress));
            }

            @Override
            public void onTouchStart(Slider slider) { }

            @Override
            public void onTouchEnd(Slider slider) { }
        });

        // Sets connectingLineWeight
        final Text connectingLineWeight = (Text) findComponentById(ResourceTable.Id_connectingLineWeight);
        Slider connectingLineWeightSeek = (Slider) findComponentById(ResourceTable.Id_connectingLineWeightSeek);
        connectingLineWeightSeek.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
                rangebar.setConnectingLineWeight(convertDpToPixel(progress, MainAbilitySlice.this));
                connectingLineWeight.setText(String.format(Locale.ROOT, "connectingLineWeight = %ddp", progress));
            }

            @Override
            public void onTouchStart(Slider slider) { }

            @Override
            public void onTouchEnd(Slider slider) { }
        });

        // Sets Pin radius
        final Text pinRadius = (Text) findComponentById(ResourceTable.Id_pinSize);
        Slider pinRadiusSeek = (Slider) findComponentById(ResourceTable.Id_pinSizeSeek);
        pinRadiusSeek.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
                rangebar.setPinRadius(convertDpToPixel(progress, MainAbilitySlice.this));
                pinRadius.setText(String.format(Locale.ROOT, "Pin Size = %ddp", progress));
            }

            @Override
            public void onTouchStart(Slider slider) { }

            @Override
            public void onTouchEnd(Slider slider) { }
        });

        // Sets Thumb boundary Radius
        final Text thumbBoundarySize = (Text) findComponentById(ResourceTable.Id_thumbBoundarySize);
        Slider thumbBoundarySeek = (Slider) findComponentById(ResourceTable.Id_thumbBoundarySeek);
        thumbBoundarySeek.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
                rangebar.setThumbBoundarySize(convertDpToPixel(progress, MainAbilitySlice.this));
                thumbBoundarySize.setText(String.format(Locale.ROOT, "Thumb Boundary Size = %ddp", progress));
            }

            @Override
            public void onTouchStart(Slider slider) { }

            @Override
            public void onTouchEnd(Slider slider) { }
        });

        // Setting Color Attributes---------------------------------

        // Sets barColor
        barColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.BAR_COLOR, mBarColor, mBarColor);
            }
        });

        // Set tickLabelColor
        tickLabelColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.TICK_LABEL_COLOR, mTickLabelColor, mTickLabelColor);
            }
        });

        // Set tickLabelSelectedColor
        tickLabelSelectedColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.TICK_LABEL_SELECTED_COLOR, mTickLabelSelectedColor,
                        mTickLabelSelectedColor);
            }
        });

        // Sets connectingLineColor
        connectingLineColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.CONNECTING_LINE_COLOR, mConnectingLineColor,
                        mConnectingLineColor);
            }
        });

        // Sets pinColor
        pinColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.PIN_COLOR, mPinColor, mPinColor);
            }
        });
        // Sets pinTextColor
        pinTextColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.TEXT_COLOR, mTextColor, mTextColor);
            }
        });
        // Sets tickColor
        tickColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.TICK_COLOR, mTickColor, mTickColor);
            }
        });
        // Sets thumbColor
        thumbColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.THUMB_COLOR, mThumbColor, mThumbColor);
            }
        });

        thumbBoundaryColor.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                initColorPicker(ComponentColor.THUMB_BOUNDARY_COLOR, mThumbBoundaryColor, mThumbBoundaryColor);
            }
        });

        Checkbox cbRoundedBar = (Checkbox) findComponentById(ResourceTable.Id_cbRoundedBar);
        cbRoundedBar.setChecked(rangebar.isBarRounded());
        cbRoundedBar.setCheckedStateChangedListener(new AbsButton.CheckedStateChangedListener() {
            @Override
            public void onCheckedChanged(AbsButton absButton, boolean isChecked) {
                rangebar.setBarRounded(isChecked);
            }
        });

        tickTopLabelsButton.setClickedListener(new Component.ClickedListener() {
            private CharSequence[] mLabels;
            @Override
            public void onClick(Component component) {
                final CharSequence[] labels = rangebar.getTickTopLabels();

                if (labels != null) {
                    mLabels = labels;
                    rangebar.setTickTopLabels(null);
                } else {
                    rangebar.setTickTopLabels(mLabels);
                }
            }
        });

        tickBottomLabelsButton.setClickedListener(new Component.ClickedListener() {
            private CharSequence[] mLabels;

            @Override
            public void onClick(Component component) {
                final CharSequence[] labels = rangebar.getTickBottomLabels();

                if (labels != null) {
                    mLabels = labels;
                    rangebar.setTickBottomLabels(null);
                } else {
                    rangebar.setTickBottomLabels(mLabels);
                }
            }
        });

        thumbListContainerView.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Intent intent = new Intent();
                intent.addFlags(Intent.FLAG_ABILITY_NEW_MISSION);
                present(new ListContainerSlice(), intent);
            }
        });
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    /**
     * Sets the changed color using the ColorPickerDialog.
     *
     * @param resourceId specifying which input is being used
     * @param newColor  Integer specifying the new color to be selected.
     */

    @Override
    public void onColorSelected(int newColor, ComponentColor resourceId) {
        LogUtil.debug(TAG, " new color = " + newColor + ",compomentColor = "
                + resourceId);
        String hexColor = String.format("#%06X", (0xFFFFFF & newColor));

        switch (resourceId) {
            case BAR_COLOR:
                mBarColor = newColor;
                rangebar.setBarColor(newColor);
                final Text barColorText = (Text) findComponentById(ResourceTable.Id_barColor);
                barColorText.setText("barColor = " + hexColor);
                barColorText.setTextColor(new Color(newColor));
                break;

            case TEXT_COLOR:
                mTextColor = newColor;
                rangebar.setPinTextColor(newColor);
                final Text textColorText = (Text) findComponentById(ResourceTable.Id_textColor);
                textColorText.setText("textColor = " + hexColor);
                textColorText.setTextColor(new Color(newColor));
                break;

            case CONNECTING_LINE_COLOR:
                mConnectingLineColor = newColor;
                rangebar.setConnectingLineColor(newColor);
                final Text connectingLineColorText = (Text) findComponentById(
                        ResourceTable.Id_connectingLineColor);
                connectingLineColorText.setText("connectingLineColor = " + hexColor);
                connectingLineColorText.setTextColor(new Color(newColor));
                break;

            case PIN_COLOR:
                mPinColor = newColor;
                rangebar.setPinColor(newColor);
                final Text pinColorText = (Text) findComponentById(ResourceTable.Id_pinColor);
                pinColorText.setText("pinColor = " + hexColor);
                pinColorText.setTextColor(new Color(newColor));
                break;

            case TICK_COLOR:
                mTickColor = newColor;
                rangebar.setTickDefaultColor(newColor);
                final Text tickColorText = (Text) findComponentById(ResourceTable.Id_tickColor);
                tickColorText.setText("tickColor = " + hexColor);
                tickColorText.setTextColor(new Color(newColor));
                break;

            case THUMB_COLOR:
                mThumbColor = newColor;
                rangebar.setThumbColor(newColor);
                final Text thumbColorText = (Text) findComponentById(ResourceTable.Id_thumbColor);
                thumbColorText.setText("Thumb Color = " + hexColor);
                thumbColorText.setTextColor(new Color(newColor));
                break;

            case THUMB_BOUNDARY_COLOR:
                mThumbBoundaryColor = newColor;
                rangebar.setThumbBoundaryColor(newColor);
                final Text thumbBoundaryColorText = (Text) findComponentById(ResourceTable.Id_thumbBoundaryColor);
                thumbBoundaryColorText.setText("Thumb Boundary Color = " + hexColor);
                thumbBoundaryColorText.setTextColor(new Color(newColor));
                break;

            case TICK_LABEL_COLOR:
                mTickLabelColor = newColor;
                rangebar.setTickLabelColor(newColor);
                break;

            case TICK_LABEL_SELECTED_COLOR:
                mTickLabelSelectedColor = newColor;
                rangebar.setTickLabelSelectedColor(newColor);
                break;
        }
    }

    @Override
    public void onColorChooserDismissed(ColorPickerDialog dialog) {
        dialog.setAutoClosable(true);
        LogUtil.debug(TAG, "Color chooser dismissed!");
    }

    /**
     * Initiates the colorPicker from within a button function.
     *
     * @param componentColor    Component specifying which input is being used
     * @param initialColor Integer specifying the initial color choice. *
     * @param defaultColor Integer specifying the default color choice.
     */
    private void initColorPicker(ComponentColor componentColor, int initialColor, int defaultColor) {
        ColorPickerDialog colorPicker = new ColorPickerDialog.Builder(this, ResourceTable.String_colorPickerTitle)
                .titleSub(ResourceTable.String_colors)
                .componentColor(componentColor)
                .selectedColor(initialColor)
                .show();

        colorPicker.setOnColorSelectedListener(this);
    }

    /**
     * Used to convert dp unit to equivalent pixels on basis of device density.
     *
     * @param densityPixels A value in dp (density independent pixels) unit.
     * @param ctx Context to get resources and device specific display metrics
     * @return A float value that represent px equivalent to dp depending on device density
     */
    public static int convertDpToPixel(int densityPixels, Context ctx) {
        return AttrHelper.vp2px(densityPixels, ctx);
    }

    /**
     * Used to convert device specific pixels to density independent pixels.
     *
     * @param pixels  A value in px (pixels) unit.
     * @param ctx Context to get resources and device specific display metrics
     * @return A float value that represent dp equivalent to pixel value
     */
    public static int convertPixelsToDp(int pixels, Context ctx) {
        return (int) (pixels /  AttrHelper.getDensity(ctx) / 160 );
    }
}
